/**
 * @Author: Sun Rising
 * @Date: 2020-07-02 08:27:01
 * @Last Modified by: Sun Rising
 * @Last Modified time: 2020-07-02 08:27:01
 * @Description: 观察者模式
 */
// 观察者抽象类
abstract class Observer {
    // 观察者必须实现更新接口
    abstract updata(newVal: any, oldVal: any): void
}

// 观察者1
class Observer1 extends Observer {

    constructor(subject: Subject) {
        super();
        // 将this存放到被观察者的观察者集合中
        subject.addObserver(this)
    }

    // 响应更新通知
    updata(newVal: any, oldVal: any): void {
        console.log(`Observer1接到通知-->${oldVal}-->${newVal}`);
    }

}

// 观察者2
class Observer2 extends Observer {

    constructor(subject: Subject) {
        super();
        subject.addObserver(this)
    }

    updata(newVal: any, oldVal: any): void {
        console.log(`Observer2接到通知-->${oldVal}-->${newVal}`);
    }

}

// 被观察者
class Subject {

    // 观察者集合
    private observers: Observer[] = [];
    // 观察的参数
    private state;

    constructor() {
        this.state = new Proxy({}, {
            set: (targer, key, val) => {
                let oldVal = targer[key];
                targer[key] = val
                this.callObserver(val, oldVal)
                return true
            }
        })
    }

    // 存放到观察者集合
    public addObserver(observer: Observer) {
        this.observers.push(observer)
    }

    setState(val) {
        Object.assign(this.state, val)
    }

    // 通知观察者们
    callObserver(newVal: any, oldVal: any) {
        this.observers.forEach((observer: Observer) => {
            observer.updata(newVal, oldVal);
        })
    }

}

let subject: Subject = new Subject();
let observer1: Observer = new Observer1(subject);
let observer2: Observer = new Observer2(subject);
subject.setState({
    a: 222
})
